#include "CLController.hpp"

CLController::CLController(GAcore *gc, GAmodSettings &settings) throw (ControllerException)
:Controller(gc,settings)
{
	TemplateGAmodObjWrapper<string> *strsett;
	const char *tmp;

    this->snap_interval=25;
    this->max_generations=500;
    this->complete_snap = 0;

    //strsett = (GAmodStrSetting*) settings.get_setting("snap_interval");
    //tmp = (strsett) ? ((GAmodStrSetting*)strsett)->toStr() : NULL;

    strsett = (TemplateGAmodObjWrapper<string>*)settings.get_setting("snap_interval");
    tmp = (strsett) ? strsett->value.c_str() : NULL;

    if(!tmp)
    {
        IF_DBG_INFO(printf("[WARN] CLController::CLController: snap interval non specificato, uso %d\n",this->snap_interval);)
    }
    else
    {
        this->snap_interval = atoi(tmp);

        IF_DBG_VERB(printf("[INFO] CLController::CLController: snap_interval <%s> = %d\n",tmp,this->snap_interval);)
        if(snap_interval<=0)
            throw ControllerException("CLController::CLController: snap_interval non valido");

    }


    //strsett = (GAmodStrSetting*)settings.get_setting("max_generations");
    //tmp = (strsett) ? ((GAmodStrSetting*)strsett)->toStr() : NULL;

    strsett = (TemplateGAmodObjWrapper<string>*)settings.get_setting("max_generations");
    tmp = (strsett) ? strsett->value.c_str() : NULL;

    if(!tmp)
    {
        IF_DBG_INFO(printf("[WARN] CLController::CLController: max generations non specificato, uso %d\n",this->max_generations);)
    }
    else
    {
        this->max_generations = atoi(tmp);

        IF_DBG_VERB(printf("[INFO] CLController::CLController: max_generations <%s> = %d\n",tmp,this->max_generations);)
        if(max_generations<=0)
            throw ControllerException("CLController::CLController: max_generations non valido");

    }

	this->max_no_progress = -1;

    strsett = (TemplateGAmodObjWrapper<string>*)settings.get_setting("max_no_progress");
    tmp = (strsett) ? strsett->value.c_str() : NULL;

    if(!tmp)
    {
        IF_DBG_INFO(printf("[WARN] CLController::CLController: max_no_progress non specificato, uso %d\n", max_no_progress);)
    }
    else
    {
        this->max_no_progress = atoi(tmp);

        IF_DBG_VERB(printf("[INFO] CLController::CLController: max_no_progress <%s> = %d\n",tmp, max_no_progress);)
        if(max_no_progress<=0)
            throw ControllerException("CLController::CLController: max_no_progress non valido");

    }


    strsett = (TemplateGAmodObjWrapper<string>*)settings.get_setting("complete_snap");
    tmp = (strsett) ? strsett->value.c_str() : NULL;


    if(!tmp)
    {
        IF_DBG_INFO(printf("[WARN] CLController::CLController: complete_snap non specificato, uso %d\n",this->complete_snap);)
    }
    else
    {
        this->complete_snap = atoi(tmp);

        IF_DBG_VERB(printf("[INFO] CLController::CLController: complete_snap <%s> = %d\n",tmp,this->complete_snap);)
        if(complete_snap!=0 && complete_snap!=1)
            throw ControllerException("CLController::CLController: complete_snap non valido");

    }

}

void CLController::start_execution() throw (ControllerException)
{
    Individuo best;

    const GAmodFloatSetting *strsett;
    //char *tmp;
    clock_t clk0, clke;

    Popolazione		pop(1);
    GAmodSettings	params;
	char			strtmp[255];
	//ArchValidator	*sv;
	int				no_progress_counter;
	float			last_score = -1, new_score;

    clk0=clock();

    for(int i=0; i<this->max_generations; i+=this->snap_interval)
    {
        try
        {
            this->myCore->runGeneration(this->snap_interval);
            this->myCore->getGenerationData(params,0);

        }catch(EHW_Exception &e)
        {
            printf("[ERROR]: %s\n",e.msg.c_str());
        }
        //pop.print_all();


        strsett = (GAmodFloatSetting*)params.get_setting("best_score");

        if(strsett)
        {
			new_score = ((GAmodFloatSetting*)strsett)->val;

			if(new_score != last_score)
				no_progress_counter = 0;

			last_score = new_score;

			no_progress_counter+= snap_interval;
			if(no_progress_counter >= max_no_progress)
				return;

            printf("\nbest = %f = %f\n",new_score,100*new_score/this->myValidator->getMaxScore() );
            if(((GAmodFloatSetting*)strsett)->val == this->myValidator->getMaxScore())
            {
                printf("\nEvolution Complete!");
                clke=clock();
                printf("\nEvolution Time:\t%f\n",(clke-clk0)/(float)(CLOCKS_PER_SEC));
                printf("Generation number:\t%d\n",i + snap_interval);

                this->myCore->getPopolazione(pop);
                best = pop.getBestIndividuo();
                //best.create_dxf_rp("best.dxf");
                pop.save_to_file("snap//bestpop.dat");
				best.print_geno();

				sprintf(strtmp,"snap/best",i+snap_interval);
				myValidator->snapIndividuo(best,strtmp);

                return;
            }
        }



        strsett = (GAmodFloatSetting*)params.get_setting("mean_score");
        if(strsett)
            printf("mean = %f\n",((GAmodFloatSetting*)strsett)->val);


        strsett = (GAmodFloatSetting*)params.get_setting("var_score");
        if(strsett)
            printf("var = %f\n",((GAmodFloatSetting*)strsett)->val);


        strsett = (GAmodFloatSetting*)params.get_setting("n_mut");
        if(strsett)
            printf("n_mut = %f\n",((GAmodFloatSetting*)strsett)->val);


        strsett = (GAmodFloatSetting*)params.get_setting("n_cross");
        if(strsett)
            printf("n_cross = %f\n",((GAmodFloatSetting*)strsett)->val);

        strsett = (GAmodFloatSetting*)params.get_setting("ham_best");
        if(strsett)
            printf("ham_best = %f\n",((GAmodFloatSetting*)strsett)->val);
        //printf("FN\n");

        strsett = (GAmodFloatSetting*)params.get_setting("num_cores");
        if(strsett)
        {
            //printf("num_cores = %d\n",(int)((GAmodFloatSetting*)strsett)->val);
            int nc = (int) ((GAmodFloatSetting*)strsett)->val;
            char strtmp[512];

            for(int j=0; j<nc; j++)
            {
                sprintf(strtmp,"best_score_%d",j);
                strsett = (GAmodFloatSetting*)params.get_setting(strtmp);
                if(strsett)
                    printf(" best[%d] = %.3f",j,((GAmodFloatSetting*)strsett)->val);

                sprintf(strtmp,"mean_score_%d",j);
                strsett = (GAmodFloatSetting*)params.get_setting(strtmp);
                if(strsett)
                    printf("\tmean[%d] = %.3f",j,((GAmodFloatSetting*)strsett)->val);


                sprintf(strtmp,"ham_best_%d",j);
                strsett = (GAmodFloatSetting*)params.get_setting(strtmp);
                if(strsett)
                    printf("\tham_best[%d] = %.3f\n",j,((GAmodFloatSetting*)strsett)->val);

            }

        }

		if(this->complete_snap)
		{
			try {

				myCore->getPopolazione(pop);
				best = pop.getBestIndividuo();

				sprintf(strtmp,"snap/best%04d.dxf",i+snap_interval);
				best.create_dxf_rp(strtmp);

				sprintf(strtmp,"snap/best%04d",i+snap_interval);
				myValidator->snapIndividuo(best,strtmp);

				sprintf(strtmp,"snap/pop%04d.dat",i+snap_interval);
				pop.save_to_file(strtmp);
			}
			catch (EHW_Exception &e) {
				std::string errmsg("CLController::start_execution:\n\t");
				errmsg = errmsg + e.msg;
				throw ControllerException((char*)errmsg.c_str());
			}

        }

        params.clear();
    }
	return;
}
